/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.ibatis.extension.conditions;

import com.je.ibatis.extension.conditions.interfaces.Compare;
import com.je.ibatis.extension.conditions.interfaces.Func;
import com.je.ibatis.extension.conditions.interfaces.Join;
import com.je.ibatis.extension.conditions.interfaces.Nested;
import com.je.ibatis.extension.enums.Conditions;
import com.je.ibatis.extension.enums.DbType;
import com.je.ibatis.session.CustomConfiguration;
import org.apache.ibatis.scripting.xmltags.MixedSqlNode;
import org.apache.ibatis.scripting.xmltags.SqlNode;
import org.apache.ibatis.scripting.xmltags.TextSqlNode;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.je.ibatis.extension.enums.Conditions.*;
import static com.je.ibatis.extension.toolkit.Constants.*;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

/**
 * 条件解析器
 * <p>
 * 非线程安全
 *
 * @author wangmm@ketr.com.cn
 * @date 2019/11/28
 */
public class ConditionsWrapper implements Compare<ConditionsWrapper, String>, Nested<ConditionsWrapper, ConditionsWrapper>,
        Join<ConditionsWrapper>, Func<ConditionsWrapper, String> {
    /**
     * 特殊数据库的sql is null  和 is not null的处理
     */
    protected final String[] regs = {"(\\<> #\\{(.*?)\\})","(\\!= #\\{(.*?)\\})","(\\= #\\{(.*?)\\})"};

    /**
     * sql缓冲池
     */
    protected final StringBuffer buffer = new StringBuffer();

    /**
     * sql语句
     */
    protected final StringBuffer sqlContent = new StringBuffer();

    /**
     * sql语句节点
     */
    protected final List<SqlNode> contents;

    /**
     * 参数
     */
    protected final ParameterWrapper parameter;

    /**
     * 是否为空
     */
    protected boolean isEmpty = true;

    /**
     * 私有构造函数，实例可通过builder或child方法获得
     */
    private ConditionsWrapper() {
        contents = new ArrayList<>();
        parameter = new ParameterWrapper();
    }

    private ConditionsWrapper(ParameterWrapper parameter) {
        contents = new ArrayList<>();
        this.parameter = parameter;
    }

    /**
     * 创建实例
     *
     * @return ConditionsWrapper
     */
    public static ConditionsWrapper builder() {
        return new ConditionsWrapper();
    }

    /**
     * 创建实例
     *
     * @return ConditionsWrapper
     */
    public static ConditionsWrapper builder(String applySql, Object... params) {
        return new ConditionsWrapper().apply(applySql, params);
    }

    /**
     * 创建子实例
     *
     * @return ConditionsWrapper
     */
    public ConditionsWrapper child() {
        return new ConditionsWrapper(parameter);
    }

    @Override
    public <V> ConditionsWrapper allEq(boolean condition, Map<String, V> params, boolean null2IsNull) {
        if (condition && !CollectionUtils.isEmpty(params)) {
            params.forEach((k, v) -> {
                if (!StringUtils.isEmpty(v)) {
                    eq(k, v);
                } else {
                    if (null2IsNull) {
                        isNull(k);
                    }
                }
            });
        }
        return this;
    }

    @Override
    public <V> ConditionsWrapper allEq(boolean condition, BiPredicate<String, V> filter, Map<String, V> params, boolean null2IsNull) {
        if (condition && !CollectionUtils.isEmpty(params)) {
            params.forEach((k, v) -> {
                if (filter.test(k, v)) {
                    if (!StringUtils.isEmpty(v)) {
                        eq(k, v);
                    } else {
                        if (null2IsNull) {
                            isNull(k);
                        }
                    }
                }
            });
        }
        return this;
    }

    @Override
    public ConditionsWrapper eq(boolean condition, String column, Object val) {
        if ((CustomConfiguration.dbType == DbType.OSCAR || CustomConfiguration.dbType == DbType.ORACLE) && (val == null || "".equals(val.toString()))) {
            return isNull(condition, column);
        }
        return addCondition(condition, () -> column, EMPTY, EQ, EMPTY, () -> parameter.put(val));
    }

    @Override
    public ConditionsWrapper ne(boolean condition, String column, Object val) {
        if ((CustomConfiguration.dbType == DbType.OSCAR || CustomConfiguration.dbType == DbType.ORACLE) && (val == null || "".equals(val.toString()))) {
            return isNotNull(condition, column);
        }
        return addCondition(condition, () -> column, EMPTY, NE, EMPTY, () -> parameter.put(val));
    }

    @Override
    public ConditionsWrapper gt(boolean condition, String column, Object val) {
        return addCondition(condition, () -> column, EMPTY, GT, EMPTY, () -> parameter.put(val));
    }

    @Override
    public ConditionsWrapper ge(boolean condition, String column, Object val) {
        return addCondition(condition, () -> column, EMPTY, GE, EMPTY, () -> parameter.put(val));
    }

    @Override
    public ConditionsWrapper lt(boolean condition, String column, Object val) {
        return addCondition(condition, () -> column, EMPTY, LT, EMPTY, () -> parameter.put(val));
    }

    @Override
    public ConditionsWrapper le(boolean condition, String column, Object val) {
        return addCondition(condition, () -> column, EMPTY, LE, EMPTY, () -> parameter.put(val));
    }

    @Override
    public ConditionsWrapper between(boolean condition, String column, Object val1, Object val2) {
        if (CustomConfiguration.dbType == DbType.KINGBASEES) {
            addCondition(condition, () -> column, EMPTY, GE, EMPTY, () -> parameter.put(val1));
            addCondition(condition, () -> column, EMPTY, LE, EMPTY, () -> parameter.put(val2));
            return this;
        } else {
            return addCondition(condition, () -> column, EMPTY, BETWEEN, EMPTY, () -> parameter.put(val1), EMPTY, AND, EMPTY, () -> parameter.put(val2));
        }
    }

    @Override
    public ConditionsWrapper notBetween(boolean condition, String column, Object val1, Object val2) {
        if (CustomConfiguration.dbType == DbType.KINGBASEES) {
            addCondition(condition, () -> column, EMPTY, LT, EMPTY, () -> parameter.put(val1));
            addCondition(condition, () -> column, EMPTY, GT, EMPTY, () -> parameter.put(val2));
            return this;
        } else {
            return addCondition(condition, () -> column, EMPTY, NOT, EMPTY, BETWEEN, EMPTY, () -> parameter.put(val1), AND, () -> parameter.put(val2));
        }

    }

    @Override
    public ConditionsWrapper like(boolean condition, String column, Object val) {
        return addCondition(condition, () -> column, EMPTY, LIKE, EMPTY, () -> parameter.put(PERCENT.getSqlSegment() + val + PERCENT.getSqlSegment()));
    }

    @Override
    public ConditionsWrapper notLike(boolean condition, String column, Object val) {
        return addCondition(condition, () -> column, EMPTY, NOT, EMPTY, LIKE, EMPTY, () -> parameter.put(PERCENT.getSqlSegment() + val + PERCENT.getSqlSegment()));
    }

    @Override
    public ConditionsWrapper likeLeft(boolean condition, String column, Object val) {
        return addCondition(condition, () -> column, EMPTY, LIKE, EMPTY, () -> parameter.put(PERCENT.getSqlSegment() + val));
    }

    @Override
    public ConditionsWrapper likeRight(boolean condition, String column, Object val) {
        return addCondition(condition, () -> column, EMPTY, LIKE, EMPTY, () -> parameter.put(val + PERCENT.getSqlSegment()));
    }

    @Override
    public ConditionsWrapper isNull(boolean condition, String column) {
        return addCondition(condition, () -> column, EMPTY, IS_NULL);
    }

    @Override
    public ConditionsWrapper isNotNull(boolean condition, String column) {
        return addCondition(condition, () -> column, EMPTY, IS_NOT_NULL);
    }

    @Override
    public ConditionsWrapper in(boolean condition, String column, Collection<?> coll) {
        //如果集合为 empty 拼接 column in (null)
        if (coll == null || coll.isEmpty()) {
            return inSql(condition, column, "null");
        }
        String inSql = coll.stream().map(parameter::put)
                .collect(joining(COMMA.getSqlSegment()));
        return inSql(condition, column, inSql);
    }

    @Override
    public ConditionsWrapper notIn(boolean condition, String column, Collection<?> coll) {

        //如果集合为 empty 不添加not in 条件
        if (coll == null || coll.isEmpty()) {
            return this;
        }
        String inSql = coll.stream().map(parameter::put)
                .collect(joining(COMMA.getSqlSegment()));
        return notInSql(condition, column, inSql);
    }

    @Override
    public ConditionsWrapper inSql(boolean condition, String column, String inValue) {
        return addCondition(condition, () -> column, EMPTY, IN, EMPTY, LEFT_BRACKET, () -> inValue, RIGHT_BRACKET);
    }

    @Override
    public ConditionsWrapper notInSql(boolean condition, String column, String inValue) {
        return addCondition(condition, () -> column, EMPTY, NOT, EMPTY, IN, EMPTY, LEFT_BRACKET, () -> inValue, RIGHT_BRACKET);
    }

    @Override
    public ConditionsWrapper groupBy(boolean condition, String... columns) {
        List<String> list = Arrays.asList(columns);
        if (CollectionUtils.isEmpty(list)) {
            return this;
        }
        return doIt(condition, EMPTY, GROUP_BY, EMPTY,
                () -> list.size() == 1 ? list.get(0) : list.stream().collect(joining(COMMA.getSqlSegment())));
    }

    @Override
    public ConditionsWrapper orderBy(boolean condition, boolean isAsc, String... columns) {
        List<String> list = Arrays.asList(columns);
        if (CollectionUtils.isEmpty(list)) {
            return this;
        }
        Conditions mode = isAsc ? ASC : DESC;
        doIt(condition, EMPTY, ORDER_BY, EMPTY,
                () -> list.size() == 1
                        ? EMPTY + list.get(0) + EMPTY + mode
                        : list.stream().map(column -> EMPTY + column + EMPTY + mode).collect(joining(COMMA.getSqlSegment())));
        return this;
    }

    @Override
    public ConditionsWrapper or(boolean condition) {
        if (condition) {
            buffer.append(EMPTY);
            buffer.append(OR);
        }
        return this;
    }

    /**
     * <p>
     * 普通示例:
     * apply("create_date > date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08")
     * =>
     * create_date > date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
     * <p>
     * like示例:
     * apply("name like {0}", "%jay%")
     * =>
     * "name like '%jay%'"
     * <p>
     * in示例:
     * apply("id in ({0})", Lists.newArrayList(1,2,3))
     * =>
     * and id in(1,2,3)
     *
     * @param condition 是否启用
     * @param applySql  预处理sql
     * @param value     预处理sql占位符对应的值数组
     * @return com.je.ibatis.extension.conditions.ConditionsWrapper 当前对象，实现链式操作
     */
    @Override
    public ConditionsWrapper apply(boolean condition, String applySql, Object... value) {
        if (condition && !StringUtils.isEmpty(applySql)) {
            //如果为空，且第一个追加，第一个where 就不应该以AND开头
            if(StringUtils.isEmpty(buffer.toString()) && applySql.trim().startsWith("AND")){
                String newApplySql = applySql.trim().substring("AND".length());
                return doIt(true, EMPTY, () -> formatSql(newApplySql, value));
            }if(StringUtils.isEmpty(buffer.toString()) && applySql.trim().startsWith("and")){
                String newApplySql = applySql.trim().substring("and".length());
                return doIt(true, EMPTY, () -> formatSql(newApplySql, value));
            }else{
                return doIt(true, EMPTY, () -> formatSql(applySql, value));
            }
        }
        return this;
    }

    @Override
    public ConditionsWrapper applyBefore(boolean condition, String applySql, Object... value) {
        if (condition && !StringUtils.isEmpty(applySql)) {
            String formatSql = formatSql(applySql, value) + EMPTY;
            if (isEmpty) {
                return doIt(true, () -> formatSql, EMPTY);
            } else {
                //获取原SQL
                String oldSql = getSql();
                //重置语句
                contents.clear();
                sqlContent.setLength(0);
                //增加前置语句
                contents.add(new TextSqlNode(formatSql));
                sqlContent.append(formatSql);
                //增加原有语句
                contents.add(new TextSqlNode(oldSql));
                sqlContent.append(oldSql);
            }
        }
        return this;
    }

    @Override
    public ConditionsWrapper exists(boolean condition, String existsSql) {
        return doIt(condition, EMPTY, EXISTS, () -> String.format("(%s)", existsSql));
    }

    @Override
    public ConditionsWrapper notExists(boolean condition, String notExistsSql) {
        return doIt(condition, EMPTY, NOT, EMPTY, EXISTS, () -> String.format("(%s)", notExistsSql));
    }

    @Override
    public ConditionsWrapper and(boolean condition, Consumer<ConditionsWrapper> consumer) {
        return addNestedCondition(condition, false, consumer);
    }

    @Override
    public ConditionsWrapper or(boolean condition, Consumer<ConditionsWrapper> consumer) {
        return addNestedCondition(condition, true, consumer);
    }

    @Override
    public ConditionsWrapper nested(boolean condition, Consumer<ConditionsWrapper> consumer) {
        return addNestedCondition(condition, null, consumer);
    }

    /**
     * 拼接 AND
     *
     * @param condition 是否执行
     */
    protected ConditionsWrapper and(boolean condition) {
        if (condition && !isEmpty && !buffer.toString().trim().endsWith(OR.getSqlSegment()) && !buffer.toString().trim().toUpperCase().endsWith(WHERE.getSqlSegment().trim())) {
            buffer.append(EMPTY);
            buffer.append(AND);
        }
        return this;
    }

    /**
     * 添加普通条件
     *
     * @param condition 是否执行
     */
    protected ConditionsWrapper addCondition(boolean condition, ISqlSegment... sqlSegments) {
        if (condition) {
            and(true).doIt(EMPTY).doIt(sqlSegments).doIt(EMPTY);
        }
        return this;
    }

    /**
     * 多重嵌套查询条件
     *
     * @param condition 查询条件值
     */
    protected ConditionsWrapper addNestedCondition(boolean condition, Boolean isOr, Consumer<ConditionsWrapper> consumer) {
        if (condition) {
            //创建子条件实例
            final ConditionsWrapper instance = new ConditionsWrapper(parameter);
            consumer.accept(instance);
            if (!instance.isEmpty()) {
                if (isOr == null) {
                } else if (isOr) {
                    this.or();
                } else {
                    this.and(true);
                }
                doIt(LEFT_BRACKET).flush();
                contents.add(instance.getSqlNode());
                sqlContent.append(instance.getSql());
                return doIt(RIGHT_BRACKET);
            }
        }
        return this;
    }

    /**
     * 对sql片段进行组装
     *
     * @param sqlSegments sql片段数组
     * @return ConditionsWrapper
     */
    protected ConditionsWrapper doIt(ISqlSegment... sqlSegments) {
        return doIt(true, sqlSegments);
    }

    /**
     * 对sql片段进行组装
     *
     * @param condition   是否执行
     * @param sqlSegments sql片段数组
     * @return ConditionsWrapper
     */
    protected ConditionsWrapper doIt(boolean condition, ISqlSegment... sqlSegments) {
        if (condition) {
            //非空
            isEmpty = false;
            //将sql加入缓冲池
            Arrays.asList(sqlSegments).forEach(p -> buffer.append(p.getSqlSegment()));
        }
        return this;
    }

    /**
     * 格式化sql,设置预处理参数
     * <p>
     * 普通示例:
     * formatSql("create_date > date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08")
     * =>
     * create_date > date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
     * <p>
     * like示例:
     * formatSql("name like {0}", "%jay%")
     * =>
     * "name like '%jay%'
     * <p>
     * in示例:
     * formatSql("id in ({0})", Lists.newArrayList(1,2,3))
     * =>
     * and id in(1,2,3)
     *
     * @param sqlStr 原始sql
     * @param params 参数数组
     * @return java.lang.String
     */
    protected final String formatSql(String sqlStr, Object... params) {
        if (StringUtils.isEmpty(sqlStr)) {
            return null;
        }
        if (params != null) {
            //变遍历参数
            for (int i = 0; i < params.length; ++i) {
                Object value = params[i];
                String key;
                //in类型特殊处理  示例： name like {0} and id in ({1})
                if (value instanceof Collection) {
                    Collection<?> coll = (Collection) value;
                    key = coll.stream().map(parameter::put)
                            .collect(joining(COMMA.getSqlSegment()));
                } else if (value instanceof Object[]) {
                    Object[] values = (Object[]) value;
                    Collection<?> coll = Arrays.stream(values).collect(toList());
                    key = coll.stream().map(parameter::put)
                            .collect(joining(COMMA.getSqlSegment()));
                } else {
                    //将参数加入参数集合
                    key = parameter.put(params[i]);
                }
                //替换占位符为变量名
                sqlStr = sqlStr.replace(String.format("{%s}", i), key);
            }
        }
        return sqlStr;
    }

    /**
     * sql缓冲刷新
     */
    public ConditionsWrapper flush() {
        if (buffer.length() > 0) {
            contents.add(new TextSqlNode(buffer.toString()));
            sqlContent.append(buffer.toString());
            buffer.setLength(0);
        }
        return this;
    }

    /**
     * 获取Sql节点
     *
     * @return SqlNode
     */
    public SqlNode getSqlNode() {
        flush();
        //神通数据库不支持 xx!='' 或 xx=''，应以 is not null 或 is null 代替
        if (CustomConfiguration.dbType == DbType.OSCAR || CustomConfiguration.dbType == DbType.ORACLE || CustomConfiguration.dbType == DbType.KINGBASEES) {
            String sqlStr = getSql();
            if(sqlStr.contains(" where ")){
                // 非预处理空值sql <>'' !='' =''   原逻辑 不改
                String ifWhere = sqlStr.toLowerCase();
                String topSql = sqlStr.substring(0, ifWhere.indexOf(" where "));
                String whereSql = sqlStr.substring(ifWhere.indexOf(" where "));
                whereSql
                        .replaceAll("<>''", " is not null ")
                        .replaceAll("<> ''", " is not null ")
                        .replaceAll("!=''", " is not null ")
                        .replaceAll("!= ''", " is not null ")
                        .replaceAll("!=null", " is not null ")
                        .replaceAll("!= null", " is not null ")
                        .replaceAll("=''", " is null ")
                        .replaceAll("= ''", " is null ")
                        .replaceAll("=null", " is null ")
                        .replaceAll("= null", " is null ");
                sqlStr = topSql + whereSql;
            }else{
                // 预处理空值
                for (int i = 0; i < regs.length; i++) {
                    String reg = regs[0];
                    Pattern pattern = Pattern.compile(reg, Pattern.MULTILINE);
                    Matcher matcher = pattern.matcher(sqlStr);
                    //2.取值
                    while (matcher.find()) {
                        // p = <> #{wrapper.parameter.wrapper0}
                        String group = matcher.group();
                        String[] matchers = group.split("\\.");
                        String wrappers = matchers[matchers.length-1];
                        String wrapper = wrappers.substring(0,wrappers.length()-1);
                        //获取值
                        if(StringUtils.isEmpty(parameter.get(wrapper)) || "null".equals(parameter.get(wrapper))){
                            if(i == 2){
                                sqlStr = sqlStr.replace(group, " is null ");
                            }else{
                                sqlStr = sqlStr.replace(group, " is not null ");
                            }
                        }
                    }
                }
            }
            contents.clear();
            contents.add(new TextSqlNode(sqlStr));
            sqlContent.setLength(0);
            if (CustomConfiguration.dbType == DbType.KINGBASEES && CustomConfiguration.isR6){
                sqlStr = sqlStr.replaceAll(" like "," ilike ").replaceAll(" LIKE "," ILIKE ");
            }
            sqlContent.append(sqlStr);
        }
        return new MixedSqlNode(contents);
    }

    /**
     * 设置表名
     *
     * @param table 参数
     * @return ConditionsWrapper
     */
    public ConditionsWrapper table(String table) {
        if (!StringUtils.isEmpty(table)) {
            parameter.put(KEY_TABLE_CODE, table);
        }
        return this;
    }

    /**
     * 获取tableCode
     *
     * @return java.lang.String
     */
    public String getTable() {
        return parameter.get(KEY_TABLE_CODE) == null ? null : parameter.get(KEY_TABLE_CODE).toString();
    }

    /**
     * 设置功能Code
     *
     * @param function 参数
     * @return ConditionsWrapper
     */
    public ConditionsWrapper function(String function) {
        if (!StringUtils.isEmpty(function)) {
            parameter.put(KEY_FUNCTION_CODE, function);
        }
        return this;
    }

    /**
     * 获取查询列
     *
     * @return java.lang.String
     */
    public String getSelectColumns() {
        return parameter.get(KEY_SELECT_COLUMN) == null ? null : parameter.get(KEY_SELECT_COLUMN).toString();
    }

    /**
     * 指定查询列
     *
     * @param selectColumns 参数
     * @return ConditionsWrapper
     */
    public ConditionsWrapper selectColumns(String selectColumns) {
        if (!StringUtils.isEmpty(selectColumns)) {
            parameter.put(KEY_SELECT_COLUMN, selectColumns);
        }
        return this;
    }

    /**
     * 获取funcCode
     *
     * @return java.lang.String
     */
    public String getFunction() {
        return parameter.get(KEY_FUNCTION_CODE) == null ? null : parameter.get(KEY_FUNCTION_CODE).toString();
    }

    /**
     * 获取wrapper完整Sql
     *
     * @return java.lang.String
     */
    public String getSql() {
        flush();
        return sqlContent.toString();
    }

    /**
     * 获取完整Sql，非预处理
     * <p>
     * 示例：
     * USER_ID in (#{wrapper.parameter.wrapper1},#{wrapper.parameter.wrapper1}) and USER_NAME = #{wrapper.parameter.wrapper3}
     * =>
     * USER_ID in ('wrapper1','wrapper2') and USER_NAME = 'wrapper3'
     *
     * @return java.lang.String
     */
    public String getParameterSql() {
        String sqlStr = getSql();
        if (StringUtils.isEmpty(sqlStr)) {
            return sqlStr;
        }
        //正则匹配
        Pattern pattern = Pattern.compile("(\\#\\{(.*?)\\})", Pattern.MULTILINE);
        Matcher matcher = pattern.matcher(sqlStr);
        while (matcher.find()) {
            String p = matcher.group();
            //变量名  @USER_CODE@,@USER.userId@ 等
            String key = p.substring(2, p.length() - 1);
            key = key.replace(WRAPPER_ALIAS + ".parameter.", "");
            //获取值
            Object val = parameter.get(key);
            if (val != null) {
                //TODO 后续根据Value类型做出转换，目前value全部转换为字符串
                sqlStr = sqlStr.replace(p, "'" + val.toString() + "'");
            }
        }
        return sqlStr;
    }

    /**
     * 添加参数
     *
     * @param val 参数key
     * @return java.lang.String
     */
    public String put(Object val) {
        return parameter.put(val);
    }

    /**
     * 添加参数集
     *
     * @param map 参数集
     */
    public ConditionsWrapper putAll(Map map) {
        parameter.putAll(map);
        return this;
    }

    /**
     * 获取所有参数集
     *
     * @return ParameterWrapper wrapper中所有参数集合
     */
    public ParameterWrapper getParameter() {
        return parameter;
    }

    /**
     * 是否为空
     *
     * @return boolean
     */
    public boolean isEmpty() {
        return isEmpty;
    }

    /**
     * 是否只包含where条件
     *
     * @return boolean
     */
    public boolean isCondition() {
        String upperCase = getSql().trim().toUpperCase();
        //以指定字符开头 视为非where条件语句
        if (upperCase.startsWith(SELECT.getSqlSegment().trim())
                || upperCase.startsWith(UPDATE.getSqlSegment().trim())
                || upperCase.startsWith(INSERT.getSqlSegment().trim())
                || upperCase.startsWith(DELETE.getSqlSegment().trim())
                || upperCase.startsWith(SHOW.getSqlSegment().trim())
                || upperCase.startsWith(TRUNCATE.getSqlSegment().trim())
        ) {
            return false;
        }
        return true;
    }

    /**
     * 是否是DDL语句
     *
     * @return boolean
     */
    public boolean isDDL() {
        String upperCase = getSql().trim().toUpperCase();
        if (upperCase.startsWith(CREAT.getSqlSegment().trim() + EMPTY)
                || upperCase.startsWith(ALTER.getSqlSegment().trim() + EMPTY)
                || upperCase.startsWith(DROP.getSqlSegment().trim() + EMPTY)
                || upperCase.startsWith(IF.getSqlSegment().trim() + EMPTY)
                || upperCase.startsWith(EXEC.getSqlSegment().trim() + EMPTY)
                || upperCase.startsWith(EXECUTE.getSqlSegment().trim() + EMPTY)
                || upperCase.startsWith(COMMENT.getSqlSegment().trim() + EMPTY)) {
            return true;
        }
        return false;
    }

    /**
     * 是否包含where字符串
     * <p>
     * where只可能在apply方法中注入，所以hasWhere在apply方法赋值
     *
     * @return boolean
     */
    public boolean hasWhere() {
        return getSql().trim().toUpperCase().startsWith(WHERE.getSqlSegment().trim());
    }

    /**
     * 克隆条件对象
     *
     * @return ConditionsWrapper
     */
    @Override
    public ConditionsWrapper clone() {
        ConditionsWrapper wrapper = new ConditionsWrapper();
        wrapper.apply(this.getSql());
        wrapper.putAll(this.getParameter());
        return wrapper;
    }

    /**
     * 替换sql中的内容
     *
     * @param oldChar 要替换的字符串
     * @param newChar 替换后的字符串
     * @return ConditionsWrapper
     */
    public ConditionsWrapper replace(char oldChar, char newChar) {
        //获取当前完整sql
        String sql = getSql();
        //清空现有节点
        contents.clear();
        //添加替换后的sql节点
        contents.add(new TextSqlNode(sql.replace(oldChar, newChar)));
        return this;
    }
}